package cn.micai.base.math;

import java.text.DecimalFormat;
import java.util.*;

/**
 * 描述：红包算法
 * <p>
 *
 * @author: 赵新国
 * @date: 2018/4/10 13:57
 */
public class RedEnvelopeAlgorithm {

    /**
     * 红包算法(不是很稳定，在max过大时红包的量过于极端)
     * @param money 红包总金额
     * @param num 红包数量
     * @param max 每个红包最大金额(建议max = money / num * 2)(如果max过于庞大，造成极端的可能性非常大)
     * @return java.util.List<java.lang.Double>
     */
    public static List<Double> getMoney(double money, int num, float max) {
        if ((money / num) < 0.01) {
            // 如果红包按照每个人0.01都不够分配，则返回null
            return null;
        }
        if (0.01 == (money / num)) {
            // 如果这个红包分配下来每个人都是0.01，直接返回
            double baseDouble [] = new double[num];
            Arrays.fill(baseDouble, 0.01);
            List<Double> baseList = new ArrayList<>();
            for (double d : baseDouble) {
                baseList.add(d);
            }
            return baseList;
        }
        if (num * max < money) {
            // 每个人最大值都不能达到满额，则返回null
            return null;
        }
        Random r = new Random();
        DecimalFormat format = new DecimalFormat(".##");

        double[] dou = new double[num];
        double redMoney = 0;
        double nextMoney = money;
        double sum = 0;
        int index = 0;

        for (int i = num; i > 0; i--) {
            if (i == 1) {
                dou[index] = nextMoney;
            } else {
                while (true) {
                    String str = format.format(r.nextDouble() * nextMoney);
                    redMoney = Double.parseDouble(str);

                    if (redMoney > max || max * (i - 1) < (money - sum - redMoney) || (money - sum - redMoney) < (i - 1) * 0.01) {
                        // 如果本次红包大于max则重来
                        // 如果本次红包结束，且接下来每个人都是最大值之和小于剩余的钱（也就是人都抢完红包了，还有剩余的钱）则重来
                        // 如果本次红包结束，且接下来每个人都是最小值之和大于剩余的钱（也就是人都抢完红包了，钱不够）则重来
                        continue;
                    }

                    if (redMoney > 0 && redMoney <= nextMoney) {
                        // 本次红包必须大于0
                        // 本次红包必须小于或等于nextMoney
                        break;
                    }
                }
                nextMoney = Double.parseDouble(format.format(nextMoney - redMoney));
                sum = sum + redMoney;
                dou[index] = redMoney;
                index++;
            }
        }
        // 数组转换list，随机打乱顺序
        List<Double> list = new ArrayList<>();
        for (double d : dou) {
            list.add(d);
        }
        Collections.shuffle(list);
        return list;
    }

    public static void main(String [] args) {
        List<Double> doubleList = RedEnvelopeAlgorithm.getMoney(5, 5, (5/5*2));
        for (double d : doubleList) {
            System.out.println(d);
        }
    }


}
